﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using TRACv2.Domain.DTO;
using TRACv2.Domain.Interfaces.IRepository;
using AutoMapper;

namespace TRACv2.Persistence
{
    // Author: Ryan Redburn
    // Project: TRACv2
    // Date: 3/15/2014

    #region [ Updates ]
    
    // Author: Ryan Redburn
    // Date: 3/18/2014 - 3/21/2014
    // Revisions: Fixed minor logic and spelling errors. Added GetById() method.

    #endregion

    public class EmployeeRepository : IEmployeeRepository
    {
        #region [ Methods ]

        /// <summary>
        /// Returns all employees.
        /// </summary>
        /// <returns>IEnumerable of EmployeeDto</returns>
        public IEnumerable<EmployeeDTO> GetAll()
        {
            IEnumerable<EmployeeDTO> employees;

            // Opening entity context
            using (var context = new TRACEntities())
            {
                // Mapping retrieved dbset to targeted return type
                employees = Mapper.Map<IEnumerable<EmployeeDTO>>(context.Employees);
            }

            return employees;
        }

        /// <summary>
        /// Returns all employees with the given last name.
        /// </summary>
        /// <param name="lastName">String employee last name</param>
        /// <returns>IEnumerable of EmployeeDto</returns>
        public IEnumerable<EmployeeDTO> GetByLastName(string lastName)
        {
            // Throws an exception for invalid code value
            if (String.IsNullOrWhiteSpace(lastName))
                throw new ArgumentNullException("lastName", "lastName does not accept a null or empty string as an argument.");

            IEnumerable<EmployeeDTO> employees;

            // Opening entity context
            using (var context = new TRACEntities())
            {
                // Mapping retrieved dbset to targeted return type
                employees = Mapper.Map<IEnumerable<EmployeeDTO>>(context.Employees.Where(e => e.Person.LastName == lastName));
            }

            return employees;
        }

        /// <summary>
        /// Returns an employee with the given id. Throws an exception if no employee is found.
        /// </summary>
        /// <param name="id">Integer employee id</param>
        /// <returns>EmployeeDto</returns>
        public EmployeeDTO GetById(int id)
        {
            // Throws an exception for invalid id value
            if (id < 1)
                throw new ArgumentOutOfRangeException("id", "id does not accept an integer less than one as an argument.");

            EmployeeDTO employee;

            // Opening entity context
            using (var context = new TRACEntities())
            {
                // Mapping retrieved dbset to targeted return type
                employee = Mapper.Map<EmployeeDTO>(context.Employees.SingleOrDefault(e => e.Id == id));

                // Throws an exception if no employee is found
                if (employee == null)
                    throw new InvalidOperationException("No employee matching the given id was found.");
            }

            return employee;
        }

        /// <summary>
        /// Returns an employee with the given code. Throws an exception if no employee is found.
        /// </summary>
        /// <param name="id">String employee code</param>
        public EmployeeDTO GetByCode(string code)
        {
            // Throws an exception for invalid id value
            if (String.IsNullOrWhiteSpace(code))
                throw new ArgumentNullException("code", "code does not accept a null or empty string as an argument.");

            EmployeeDTO employee;

            // Opening entity context
            using (var context = new TRACEntities())
            {
                // Mapping retrieved dbset to targeted return type
                employee = Mapper.Map<EmployeeDTO>(context.Employees.SingleOrDefault(e => e.Code == code));

                // Throws an exception if no employee is found
                if (employee == null)
                    throw new InvalidOperationException("No employee matching the given code was found.");
            }

            return employee;
        }

        #endregion
    }
}
